/*
 * test_detect.cpp
 *
 *  Created on: 2016年3月19日
 *      Author: guyadong
 */
#include <iostream>
#include <cmath>
#include <utility>
#include "cmdline.h"
#include "file_utilits.h"
#include "time_utilits.h"
#include "string_utils.h"
#include "detect_cl.h"
#include "img_tool.h"
using namespace gdface;
const static std::string SUFFIX_JPG=".jpg";
const static std::string SUFFIX_JPEG=".jpeg";
/*
 * 对指定的jpeg图像文件执行人脸检测
 * */
void detect_face(const detect_param &param,const std::string &file,size_t test_count=1,bool show_gray=false){
	// test_count为0时抛出异常
	throw_if_msg (0==test_count,"test_count must not be 0")	
	auto jpeg_data=gdface::load_binary_file(file.data());
	auto gray_image=img_tools::decode_image(img_tools::GF_FMT_JPG,jpeg_data.data(),jpeg_data.size(),true);
	throw_if_msg(0==gray_image.pixels.size(),"decode_image fail")
	if(show_gray)
		img_tools::display(gray_image,"original gray image");
	object_info_vector detected_objects;
	tls_clock_probe.start();
	if(test_count>1){
		for (decltype(test_count) i = 0; i < test_count;++i)
			detected_objects = detect_cl::detect(gray_image, param);
	}else if(1==test_count){
		// 使用右值引用版本
		detected_objects = detect_cl::detect(std::move(gray_image), param);
	}
	auto time_cost = tls_clock_probe.end()/test_count;
	// 在原始图像上显示检测结果
	img_tools::display_face_rect_t(img_tools::decode_image(img_tools::GF_FMT_JPG, jpeg_data.data(), jpeg_data.size()), detected_objects, true,"file:", get_file_name(file), ",OpenCL:",test_count," times,average=", time_cost," seconds ",1/time_cost," fps ");

}
int main(int argc, char * argv[]){
	cmdline::parser parser;
	// 命令行参数定义
	// 必填参数 指定待检测的图像文件或文件夹
	parser.add<std::string>("jpeg", 'j', "jpeg image file or folder that contain jpeg image files", true);
	// 可选参数 检测次数，仅当jpeg参数为文件的时候有效
	parser.add("count", 'c', "test count,invalid only jpeg is file", false, int(1)); 
	// 可选参数, 检测窗口放大倍率(>1)
	parser.add("step", 's', "scale ratio", false,DETECT_WIN_SCALE_RATIO); 
	// 可选参数, 最大检测窗口与图像尺寸(长宽最小者,下同)的比例
	parser.add("max", '\0', "max detect size ratio", false, DEFAULT_MAX_DETECT_WIN_RATIO); 
	// 可选参数, 最小检测窗口与图像尺寸的比例
	parser.add("min", '\0', "min detect size ratio", false, 0.0f); 
	// 可选参数, 小图优先，指定时从最小检测窗口开始逐级放大检测，默认从最大检测窗口开始逐级缩小
	parser.add("minfirst", '\0', "detect from min ratio");
	// 可选参数, 指定时显示逐级调试图像窗口，默认不显示
	parser.add("debugshow", '\0', "show image for debug"); 
	// 可选参数, 显示OpenCL kernel输出的调试信息，默认不显示
	parser.add("kernelmsg", '\0', "show debug msg from kernel"); 
	// 解析命令行参数
	parser.parse_check(argc, argv);
	detect_cl::set_global_run_config(parser.exist("debugshow"),parser.exist("kernelmsg"));
	// detecl_cl SDK初始化
	detect_cl::init(parser.get<float>("step"));
	try{
		auto input_jpg_file = parser.get<std::string>("jpeg");
		auto jpeg_is_folder = gdface::is_folder(input_jpg_file);

		auto test_count = jpeg_is_folder ? 1 : parser.get<int>("count");
		object_info_vector detected_objects;
		// 根据命令行解析的参数设置检测参数
		auto param = detect_param_builder()
			.set_max_size_ratio(parser.get<float>("max"))
			.set_min_size_ratio(parser.get<float>("min"))
			.set_min_first(parser.exist("minfirst"))
			.build();

		if(jpeg_is_folder){
			// 对指定目录下的所有jpeg图像文件执行人脸检测
			for_each_file(parser.get<std::string>("jpeg"),
				[&](const char*path,const char* name){
				// 包含路径的完整文件名
				auto full_path=std::string(path).append({file_sepator()}).append(name);
					std::string lower_name=tolower(std::string(name));
					if(end_with(lower_name,SUFFIX_JPG)||end_with(lower_name,SUFFIX_JPEG)){
						detect_face(param,full_path);
					}
				return false;
			},true);
		}
		else{
			// 对单个文件执行人脸检测
			detect_face(param,input_jpg_file,test_count,true);
		}
	}catch(std::exception &e){
		std::cout<<"exception:"<<e.what()<<std::endl;
	}catch(...){
		std::cout<<"exception:unknow"<<std::endl;
	}
}




